import matplotlib.pyplot as plt
import numpy as np
import csv

plt.rcParams['font.family'] = 'Times New Roman'
plt.rcParams['font.weight'] = 'bold'
plt.rcParams['mathtext.fontset'] = 'stix'



def _draw_box():
    random_dists = ['Normal(1, 1)', 'Lognormal(1, 1)', 'Exp(1)', 'Gumbel(6, 4)',
                    'Triangular(2, 9, 11)']
    N = 500

    norm = np.random.normal(1, 1, N)
    logn = np.random.lognormal(1, 1, N)
    expo = np.random.exponential(1, N)
    gumb = np.random.gumbel(6, 4, N)
    tria = np.random.triangular(2, 9, 11, N)

    # Generate some random indices that we'll use to resample the original data
    # arrays. For code brevity, just use the same random indices for each array
    bootstrap_indices = np.random.randint(0, N, N)

    data = [
        norm, norm[bootstrap_indices],
        logn, logn[bootstrap_indices],
        expo, expo[bootstrap_indices],
        gumb, gumb[bootstrap_indices],
        tria, tria[bootstrap_indices],
    ]

    fig, ax1 = plt.subplots(figsize=(10, 6))
    fig.canvas.manager.set_window_title('A Boxplot Example')
    fig.subplots_adjust(left=0.075, right=0.95, top=0.9, bottom=0.25)
    pos = np.arange(6).tolist() + 1
    print(pos)
    bp = ax1.boxplot(data[0], notch=False, sym='+', vert=True, whis=1.5, positions=pos)
    bp = ax1.boxplot(data[1], notch=False, sym='+', vert=True, whis=1.5, positions=pos)
    plt.setp(bp['boxes'], color='black')
    plt.setp(bp['whiskers'], color='black')
    plt.setp(bp['fliers'], color='red', marker='+')

    # Add a horizontal grid to the plot, but make it very light in color
    # so we can use it for reading data values but not be distracting
    ax1.yaxis.grid(True, linestyle='-', which='major', color='lightgrey',
                   alpha=0.5)

    ax1.set(
        axisbelow=True,  # Hide the grid behind plot objects
        title='Comparison of IID Bootstrap Resampling Across Five Distributions',
        xlabel='Distribution',
        ylabel='Value',
    )

    # Now fill the boxes with desired colors
    box_colors = ['darkkhaki', 'royalblue']
    num_boxes = len(data)
    medians = np.empty(num_boxes)
    for i in range(num_boxes):
        box = bp['boxes'][i]
        box_x = []
        box_y = []
        for j in range(5):
            box_x.append(box.get_xdata()[j])
            box_y.append(box.get_ydata()[j])
        box_coords = np.column_stack([box_x, box_y])
        # Alternate between Dark Khaki and Royal Blue
        ax1.add_patch(Polygon(box_coords, facecolor=box_colors[i % 2]))
        # Now draw the median lines back over what we just filled in
        med = bp['medians'][i]
        median_x = []
        median_y = []
        for j in range(2):
            median_x.append(med.get_xdata()[j])
            median_y.append(med.get_ydata()[j])
            ax1.plot(median_x, median_y, 'k')
        medians[i] = median_y[0]
        # Finally, overplot the sample averages, with horizontal alignment
        # in the center of each box
        ax1.plot(np.average(med.get_xdata()), np.average(data[i]),
                 color='w', marker='*', markeredgecolor='k')

    # Set the axes ranges and axes labels
    ax1.set_xlim(0.5, num_boxes + 0.5)
    top = 40
    bottom = -5
    ax1.set_ylim(bottom, top)
    ax1.set_xticklabels(np.repeat(random_dists, 2),
                        rotation=45, fontsize=8)

    # Due to the Y-axis scale being different across samples, it can be
    # hard to compare differences in medians across the samples. Add upper
    # X-axis tick labels with the sample medians to aid in comparison
    # (just use two decimal places of precision)
    pos = np.arange(num_boxes) + 1
    upper_labels = [str(round(s, 2)) for s in medians]
    weights = ['bold', 'semibold']
    for tick, label in zip(range(num_boxes), ax1.get_xticklabels()):
        k = tick % 2
        ax1.text(pos[tick], .95, upper_labels[tick],
                 transform=ax1.get_xaxis_transform(),
                 horizontalalignment='center', size='x-small',
                 weight=weights[k], color=box_colors[k])

    # Finally, add a basic legend
    fig.text(0.80, 0.08, f'{N} Random Numbers',
             backgroundcolor=box_colors[0], color='black', weight='roman',
             size='x-small')
    fig.text(0.80, 0.045, 'IID Bootstrap Resample',
             backgroundcolor=box_colors[1],
             color='white', weight='roman', size='x-small')
    fig.text(0.80, 0.015, '*', color='white', backgroundcolor='silver',
             weight='roman', size='medium')
    fig.text(0.815, 0.013, ' Average Value', color='black', weight='roman',
             size='x-small')

    plt.show()


def draw_box(x, y):
    semantic_classes = ["spleen", "right kidney", "left kidney", "gall bladder", "esophagus",
                        "liver", "stomach", "arota", "postcava", "pancreas",
                        "right adrenal gland", "left adrenal gland", "duodenum", "bladder", "prostate/uterus"]
    data = []
    for i in semantic_classes:
        data.extend(x[i])
        data.extend(y[i])

    fig, ax1 = plt.subplots(figsize=(20, 6))

    bp = ax1.boxplot(data, notch=False, sym='+', vert=True, whis=1.5)
    plt.setp(bp['boxes'], color='black')
    plt.setp(bp['whiskers'], color='black')
    plt.setp(bp['fliers'], color='red', marker='+')

    ax1.yaxis.grid(True, linestyle='-', which='major', color='lightgrey',
                   alpha=0.5)

    ax1.set(
        axisbelow=True,  # Hide the grid behind plot objects
        ylabel='DSC',
    )

    # Now fill the boxes with desired colors
    box_colors = ['darkkhaki', 'royalblue']
    num_boxes = len(data)
    medians = np.empty(num_boxes)
    for i in range(num_boxes):
        box = bp['boxes'][i]
        box_x = []
        box_y = []
        for j in range(15):
            box_x.append(box.get_xdata()[j])
            box_y.append(box.get_ydata()[j])
        box_coords = np.column_stack([box_x, box_y])
        # Alternate between Dark Khaki and Royal Blue
        ax1.add_patch(Polygon(box_coords, facecolor=box_colors[i % 2]))
        # Now draw the median lines back over what we just filled in
        med = bp['medians'][i]
        median_x = []
        median_y = []
        for j in range(2):
            median_x.append(med.get_xdata()[j])
            median_y.append(med.get_ydata()[j])
            ax1.plot(median_x, median_y, 'k')
        medians[i] = median_y[0]
        # Finally, overplot the sample averages, with horizontal alignment
        # in the center of each box
        ax1.plot(np.average(med.get_xdata()), np.average(data[i]),
                 color='w', marker='*', markeredgecolor='k')

    # Set the axes ranges and axes labels
    ax1.set_xlim(0.5, num_boxes + 0.5)
    top = 40
    bottom = -5
    ax1.set_ylim(bottom, top)
    ax1.set_xticklabels(np.repeat(semantic_classes, 2),
                        rotation=45, fontsize=8)

    # Due to the Y-axis scale being different across samples, it can be
    # hard to compare differences in medians across the samples. Add upper
    # X-axis tick labels with the sample medians to aid in comparison
    # (just use two decimal places of precision)
    pos = np.arange(num_boxes) + 1
    upper_labels = [str(round(s, 2)) for s in medians]
    weights = ['bold', 'semibold']
    for tick, label in zip(range(num_boxes), ax1.get_xticklabels()):
        k = tick % 2
        ax1.text(pos[tick], .95, upper_labels[tick],
                 transform=ax1.get_xaxis_transform(),
                 horizontalalignment='center', size='x-small',
                 weight=weights[k], color=box_colors[k])

    # Finally, add a basic legend
    fig.text(0.80, 0.08, f'Ours',
             backgroundcolor=box_colors[0], color='black', weight='roman',
             size='x-small')
    fig.text(0.80, 0.045, 'Scratch',
             backgroundcolor=box_colors[1],
             color='white', weight='roman', size='x-small')
    plt.show()



def draw_single_box(data):
    fig, ax = plt.subplots(dpi=200)
    
    location = [0.5, 5.5, 10.5]
    position = []
    
    color = ['mistyrose', 'peachpuff', 'moccasin', 
             'palegreen', 'paleturquoise',  
             'cornflowerblue', 'thistle', 'pink'
             ]
    
    for i, x in enumerate(data):
        position.append(np.add(location, [0.5 * i] * 3))
        
        ax.boxplot(x, notch=True, sym='+', widths=0.3, 
                   boxprops={'color':color[i], 'facecolor':color[i]},
                   positions=position[i], patch_artist=True)

    # x = range(1, 8)
    # ax.set_xticks(x, 
    #               ['Scratch', 'Ours', 'Swin', 'Multi', 'Deep', 'Moco', 'MAE', 'Longseq'],
    #               )
    ax.set_xticks([])
    ax.set_ylim(0, 1)
    plt.grid(ls='--', axis='both')
    plt.show()


def draw_subplot_blox():
    pass


def brats_data():
    gmm_5_3_3_5_1 = '/Users/qlc/Desktop/Results/brats/eva/gmm_5_3_3_5_1/0.csv'
    deep = '/Users/qlc/Desktop/Results/brats/eva/deep/0.csv'
    moco = '/Users/qlc/Desktop/Results/brats/eva/moco/0.csv'
    few5 = '/Users/qlc/Desktop/Results/brats/eva/few5/0.csv'
    mae = '/Users/qlc/Desktop/Results/brats/eva/mae/0.csv'
    longseq = '/Users/qlc/Desktop/Results/brats/eva/longseq/0.csv'
    swin = '/Users/qlc/Desktop/Results/brats/eva/swin/0.csv'
    multi = '/Users/qlc/Desktop/Results/brats/eva/multi/0.csv'
    
    path_list = [few5, gmm_5_3_3_5_1, swin, multi, deep, moco, mae, longseq]
    
    tc_data = []
    wt_data = []
    et_data = []
    
    for path in path_list:
        tc_data_ = []
        wt_data_ = []
        et_data_ = []
        
        with open(path, 'r') as f:
            reader = csv.reader(f)
            for i, row in enumerate(reader):
                if i != 0 and row[1] != '':
                    tc_data_.append(float(row[1]))
                    
                if i != 0 and row[2] != '':
                    wt_data_.append(float(row[2]))
                    
                if i != 0 and row[3] != '':
                    et_data_.append(float(row[3]))
    
        tc_data.append(tc_data_)
        wt_data.append(wt_data_)
        et_data.append(et_data_)       
    
    data = []
    for i in range(len(tc_data)):
        data.append([tc_data[i], wt_data[i], et_data[i]])
    
    return data
                 
                
if __name__ == "__main__":
    # data = [np.random.uniform(0.3, 0.8, 100)] * 3

    data = brats_data()
    draw_single_box(data)


